/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.beans;
import java.lang.reflect.Modifier;
import java.beans.Introspector;
import java.util.ResourceBundle;
import java.text.MessageFormat;
import org.openide.util.NbBundle;
import org.openide.src.*;
/** Singleton with static methods for generating bodies of and
* additional elements for bean patterns.
* @author Petr Hrebejk
*/
class BeanPatternGenerator extends Object {
/** The ResourceBundle */
private static final ResourceBundle bundle = NbBundle.getBundle( BeanPatternGenerator.class );
/** Constant for one Tab */
private static final String TAB = " "; // NOI18N
/** Constant for two Tabs */
private static final String TABx2 = TAB + TAB;
/** Constant for three Tabs */
private static final String TABx3 = TABx2 + TAB;
/** Generates the body of the setter method of Property.
* @param name Name of the property
* @param type Type of the property
* @param bound Is the property bound?
* @param constrained Is the property constrained?
* @param withSet Should be the set command of property private field generated.
* @param withSupport Generate the firing of (Veto|Property)Change Events?
* @param supportName Name of field containing <CODE>PropertyChangeListeners</CODE>.
* @param vetoSupportName Name of field containing <CODE>VetoableChangeListeners</CODE>.
* @return Sring containing the body of the setter method.
*/
static String propertySetterBody(String name, Type type,
boolean bound, boolean constrained,
boolean withSet, boolean withSupport,
String supportName, String vetoSupportName) {
StringBuffer setterBody = new StringBuffer( 200 );
setterBody.append( "\n" ); // NOI18N
if ( withSupport ) {
/* Generates body in the form:
PropType oldPropName = this.propName;
this.propName = propName;
changes.firePropertyChange(propName, oldPropName, propName );
*/
setterBody.append( TAB + type.toString() );
setterBody.append( " old" ).append( Pattern.capitalizeFirstLetter( name ) ); // NOI18N
setterBody.append( " = this." ).append( name ).append( ";\n"); // NOI18N
if ( constrained ) {
setterBody.append( TAB + vetoSupportName ).append( ".fireVetoableChange(\"").append( name ).append( "\", " ); // NOI18N
if ( type.isPrimitive() ) {
setterBody.append( "new ").append( getWrapperClassName( type )).append( " (" ); // NOI18N
setterBody.append( "old" ).append( Pattern.capitalizeFirstLetter( name ) ); // NOI18N
setterBody.append( "), " ); // NOI18N
setterBody.append( "new ").append( getWrapperClassName( type )).append( " (" ); // NOI18N
setterBody.append( name ).append( "));\n" ); // NOI18N
}
else {
setterBody.append( "old" ).append( Pattern.capitalizeFirstLetter( name ) ); // NOI18N
setterBody.append( ", " ).append( name ).append( ");\n" ); // NOI18N
}
if ( !bound ) {
setterBody.append( TAB + "this." ).append( name ); // NOI18N
setterBody.append( " = " ).append( name ).append( ";\n"); // NOI18N
}
}
if ( bound ) {
setterBody.append( TAB + "this." ).append( name ); // NOI18N
setterBody.append( " = " ).append( name ).append( ";\n"); // NOI18N
setterBody.append( TAB + supportName ).append( ".firePropertyChange (\"").append( name ).append( "\", " ); // NOI18N
if ( type.isPrimitive() ) {
setterBody.append( "new ").append( getWrapperClassName( type )).append( " (" ); // NOI18N
setterBody.append( "old" ).append( Pattern.capitalizeFirstLetter( name ) ); // NOI18N
setterBody.append( "), " ); // NOI18N
setterBody.append( "new ").append( getWrapperClassName( type )).append( " (" ); // NOI18N
setterBody.append( name ).append( "));\n" ); // NOI18N
}
else {
setterBody.append( "old" ).append( Pattern.capitalizeFirstLetter( name ) ); // NOI18N
setterBody.append( ", " ).append( name ).append( ");\n" ); // NOI18N
}
}
}
else if ( withSet ) {
/* Generates body in the form:
this.propName = propName;
*/
setterBody.append( TAB + "this." ); // NOI18N
setterBody.append( name );
setterBody.append( " = " ).append( name ).append( ";\n" ); // NOI18N
}
return setterBody.toString();
}
/** Generates the body of the setter method of IndexedProperty.
* @param name Name of the property
* @param indexedType Indexed type of the property
* @param bound Is the property bound?
* @param constrained Is the property constrained?
* @param withSet Should be the set command of property private field generated.
* @param withSupport Generate the firing of (Veto|Property)Change Events?
* @param supportName Name of field containing <CODE>PropertyChangeListeners</CODE>.
* @param vetoSupportName Name of field containing <CODE>VetoableChangeListeners</CODE>.
* @return Sring containing the body of the setter method.
*/
static String idxPropertySetterBody( String name, Type indexedType,
boolean bound, boolean constrained,
boolean withSet, boolean withSupport,
String supportName,
String vetoSupportName ) {
StringBuffer setterBody = new StringBuffer( 200 );
setterBody.append( "\n" ); // NOI18N
if ( withSupport && constrained ) {
setterBody.append( TAB + indexedType.toString() );
setterBody.append( " old" ).append( Pattern.capitalizeFirstLetter( name ) ); // NOI18N
setterBody.append( " = this." ).append( name ); // NOI18N
setterBody.append( "[index];\n"); // NOI18N
}
if ( withSet || withSupport ) {
/* Generates body in the form:
this.propName = propName;
*/
setterBody.append( TAB + "this." ); // NOI18N
setterBody.append( name );
setterBody.append( "[index] = " ).append( name ).append( ";\n" ); // NOI18N
}
if ( withSupport && constrained ) {
setterBody.append( TAB + "try {\n" ); // NOI18N
setterBody.append( TABx2 + vetoSupportName ).append( ".fireVetoableChange (\"").append( name ).append( "\", " ); // NOI18N
setterBody.append( "null, null );\n" ); // NOI18N
setterBody.append( TAB + "}\n" ); // NOI18N
setterBody.append( TAB + "catch(java.beans.PropertyVetoException vetoException ) {\n" ); //NOI18N
setterBody.append( TABx2 + "this." ); // NOI18N
setterBody.append( name );
setterBody.append( "[index] = old").append( Pattern.capitalizeFirstLetter( name ) ).append( ";\n" ) ; // NOI18N
setterBody.append( TABx2 + "throw vetoException;\n" ); //NOI18N
setterBody.append( TAB + "}\n" ); //NOI18N
}
if ( withSupport && bound ) {
setterBody.append( TAB + supportName ).append( ".firePropertyChange (\"").append( name ).append( "\", " ); // NOI18N
setterBody.append( "null, null );\n" ); // NOI18N
}
return setterBody.toString();
}
/** Generates the body of the getter method of Property.
* @param name Name of the property.
* @param withReturn Should be the return command with property private field generated?
* @return Sring containing the body of the getter method.
*/
static String propertyGetterBody( String name, boolean withReturn ) {
StringBuffer getterBody = new StringBuffer( 50 );
getterBody.append( "\n"); // NOI18N
if ( withReturn ) {
/* Generates body in the form:
return propName;
*/
getterBody.append( TAB + "return " ); // NOI18N
getterBody.append( name ).append( ";\n" ); // NOI18N
}
return getterBody.toString();
}
/** Generates the body of the getter method of IndexedProperty.
* @param name Name of the property.
* @param withReturn Should be the return command with property private field generated?
* @return Sring containing the body of the getter method.
*/
static String idxPropertyGetterBody( String name, boolean withReturn ) {
StringBuffer getterBody = new StringBuffer( 50 );
getterBody.append( "\n"); // NOI18N
if ( withReturn ) {
/* Generates body in the form:
return propName;
*/
getterBody.append( TAB + "return " ); // NOI18N
getterBody.append( name ).append( "[index];\n" ); // NOI18N
}
return getterBody.toString();
}
/** Gets the <CODE>PropertyChangeSupport</CODE> field in Class. Tryes to find
* a field of type <CODE>PropertyChangeSupport</CODE>. If such field doesn't
* exist creates a new one with name <CODE>propertyChangeSupport</CODE>.
* @param ce Class to operate on.
* @throws SourceException If the modification of the source is impossible.
* @return Name of foun or newly created <CODE>PropertyChangeSupport</CODE> field.
*/
static String supportField(ClassElement ce) throws SourceException {
String supportName = null;
Identifier supportId = Identifier.create( "java.beans.PropertyChangeSupport" ); // NOI18N
FieldElement[] fields = ce.getFields();
for( int i = 0; i < fields.length; i++ ) { // Try to find suitable field
if ( fields[i].getType().isClass() &&
fields[i].getType().getClassName().compareTo( supportId, false ) ) {
supportName = fields[i].getName().getName();
break;
}
}
if ( supportName == null ) { // Field not found we create new
supportName = "propertyChangeSupport"; // NOI18N
FieldElement supportField = new FieldElement();
supportField.setName( Identifier.create( supportName ) );
supportField.setType( Type.createClass( supportId ) );
supportField.setModifiers( Modifier.PRIVATE );
supportField.setInitValue( " new java.beans.PropertyChangeSupport (this)" ); // NOI18N
supportField.getJavaDoc().setRawText( bundle.getString( "COMMENT_PropertyChangeSupport" ) );
ce.addField( supportField );
}
return supportName;
}
/** Gets the <CODE>VetoableChangeSupport</CODE> field in Class. Tryes to find
* a field of type <CODE>VetoableChangeSupport</CODE>. If such field doesn't
* exist creates a new one with name <CODE>vetoableChangeSupport</CODE>.
* @param ce Class to operate on.
* @throws SourceException If the modification of the source is impossible.
* @return Name of foun or newly created <CODE>vetoableChangeSupport</CODE> field.
*/
static String vetoSupportField( ClassElement ce ) throws SourceException {
String vetoSupportName = null;
Identifier vetoSupportId = Identifier.create( "java.beans.VetoableChangeSupport" ); // NOI18N
FieldElement[] fields = ce.getFields();
for( int i = 0; i < fields.length; i++ ) { // Try to find suitable field
if ( fields[i].getType().isClass() &&
fields[i].getType().getClassName().compareTo( vetoSupportId, false ) ) {
vetoSupportName = fields[i].getName().getName();
break;
}
}
if ( vetoSupportName == null ) { // Field not found we create new
vetoSupportName = "vetoableChangeSupport"; // NOI18N
FieldElement supportField = new FieldElement();
supportField.setName( Identifier.create( vetoSupportName ) );
supportField.setType( Type.createClass( vetoSupportId ) );
supportField.setModifiers( Modifier.PRIVATE );
supportField.setInitValue( " new java.beans.VetoableChangeSupport (this)" ); // NOI18N
supportField.getJavaDoc().setRawText( bundle.getString( "COMMENT_VetoableChangeSupport" ) );
ce.addField( supportField );
}
return vetoSupportName;
}
/** If in the class don't exists methods for adding/removing PropertyChangeListeners
* for given field adds them.
* @param classElement Class to operate on.
* @param supportName The <CODE>PropertyChangeSupport</CODE> field the methods will be generated for.
* @throws SourceException If the modification of the source is impossible.
*/
static void supportListenerMethods( ClassElement classElement, String supportName )
throws SourceException {
Identifier addMethodId = Identifier.create( "addPropertyChangeListener" ); // NOI18N
MethodElement addMethod = null;
Identifier removeMethodId = Identifier.create( "removePropertyChangeListener" ); // NOI18N
MethodElement removeMethod = null;
Identifier listenerTypeId = Identifier.create( "java.beans.PropertyChangeListener" ); // NOI18N
Type listenerType = Type.createClass( listenerTypeId );
addMethod = classElement.getMethod( addMethodId, new Type[] { listenerType } );
if ( addMethod == null ) {
addMethod = new MethodElement();
addMethod.setName( addMethodId );
addMethod.setReturn( Type.VOID );
addMethod.setModifiers( Modifier.PUBLIC );
addMethod.setParameters( ( new MethodParameter[] { new MethodParameter( "l", listenerType, false ) } )); // NOI18N
StringBuffer body = new StringBuffer( 80 );
body.append( "\n" ).append( TAB + supportName ); // NOI18N
body.append( ".addPropertyChangeListener (l);\n" ); // NOI18N
addMethod.setBody( body.toString() );
/*
String comment = MessageFormat.format( bundle.getString( "COMMENT_AddPropertyChangeListener" ),
new Object[] { listenerType.getClassName().getName() } );
*/
addMethod.getJavaDoc().setRawText( bundle.getString( "COMMENT_AddPropertyChangeListener" ) );
classElement.addMethod( addMethod );
}
removeMethod = classElement.getMethod( removeMethodId, new Type[] { listenerType } );
if ( removeMethod == null ) {
removeMethod = new MethodElement();
removeMethod.setName( removeMethodId );
removeMethod.setReturn( Type.VOID );
removeMethod.setModifiers( Modifier.PUBLIC );
removeMethod.setParameters( ( new MethodParameter[] { new MethodParameter( "l", listenerType, false ) } )); // NOI18N
StringBuffer body = new StringBuffer( 80 );
body.append( "\n" ).append( TAB + supportName ); // NOI18N
body.append( ".removePropertyChangeListener (l);\n" ); // NOI18N
removeMethod.setBody( body.toString() );
removeMethod.getJavaDoc().setRawText( bundle.getString( "COMMENT_RemovePropertyChangeListener" ) );
classElement.addMethod( removeMethod );
}
}
/** If in the class don't exists methods for adding/removing VetoableChangeListeners
* for given field adds them.
* @param classElement Class to operate on.
* @param supportName The <CODE>vetoableChangeSupport</CODE> field the methods will be generated for.
* @throws SourceException If the modification of the source is impossible.
*/
static void vetoSupportListenerMethods( ClassElement classElement, String supportName )
throws SourceException {
Identifier addMethodId = Identifier.create( "addVetoableChangeListener" ); // NOI18N
MethodElement addMethod = null;
Identifier removeMethodId = Identifier.create( "removeVetoableChangeListener" ); // NOI18N
MethodElement removeMethod = null;
Identifier listenerTypeId = Identifier.create( "java.beans.VetoableChangeListener" ); // NOI18N
Type listenerType = Type.createClass( listenerTypeId );
addMethod = classElement.getMethod( addMethodId, new Type[] { listenerType } );
if ( addMethod == null ) {
addMethod = new MethodElement();
addMethod.setName( addMethodId );
addMethod.setReturn( Type.VOID );
addMethod.setModifiers( Modifier.PUBLIC );
addMethod.setParameters( ( new MethodParameter[] { new MethodParameter( "l", listenerType, false ) } )); // NOI18N
StringBuffer body = new StringBuffer( 80 );
body.append( "\n" ).append( TAB + supportName ); // NOI18N
body.append( ".addVetoableChangeListener (l);\n" ); // NOI18N
addMethod.setBody( body.toString() );
addMethod.getJavaDoc().setRawText( bundle.getString( "COMMENT_AddVetoableChangeListener" ) );
classElement.addMethod( addMethod );
}
removeMethod = classElement.getMethod( removeMethodId, new Type[] { listenerType } );
if ( removeMethod == null ) {
removeMethod = new MethodElement();
removeMethod.setName( removeMethodId );
removeMethod.setReturn( Type.VOID );
removeMethod.setModifiers( Modifier.PUBLIC );
removeMethod.setParameters( ( new MethodParameter[] { new MethodParameter( "l", listenerType, false ) } )); // NOI18N
StringBuffer body = new StringBuffer( 80 );
body.append( "\n" ).append( TAB + supportName ); // NOI18N
body.append( ".removeVetoableChangeListener (l);\n" ); // NOI18N
removeMethod.setBody( body.toString() );
removeMethod.getJavaDoc().setRawText( bundle.getString( "COMMENT_RemoveVetoableChangeListener" ) );
classElement.addMethod( removeMethod );
}
}
/** Ensures that the listeners array list exists. Used for generating
* multicast event source support implemented by java.util.ArrayList.
* Searches the source for suitable field. If the field does not exists
* creates new one.
* @param ce Class to operate on.
* @param type Type of the Event Listener.
* @throws SourceException If the modification of the source is impossible.
* @return Name of found or newly created field.
*/
static String listenersArrayListField( ClassElement ce, Type type ) throws SourceException {
String fieldName = null;
String fieldNameToFind = Introspector.decapitalize( type.getClassName().getName() ) + "List"; // NOI18N
Identifier fieldTypeId = Identifier.create( "java.util.ArrayList" ); // NOI18N
FieldElement[] fields = ce.getFields();
for( int i = 0; i < fields.length; i++ ) { // Try to find suitable field
if ( fields[i].getType().isClass() &&
fields[i].getType().getClassName().compareTo( fieldTypeId, false ) &&
fields[i].getName().getName().equals( fieldNameToFind ) ) {
fieldName = fields[i].getName().getName();
break;
}
}
if ( fieldName == null ) { // Field not found we create new
fieldName = fieldNameToFind;
FieldElement field = new FieldElement();
field.setName( Identifier.create( fieldName ) );
field.setType( Type.createClass( fieldTypeId ) );
field.setModifiers( Modifier.PRIVATE | Modifier.TRANSIENT );
String comment = MessageFormat.format( bundle.getString( "COMMENT_ListenerArrayList" ),
new Object[] { type.getClassName().getName() } );
field.getJavaDoc().setRawText( comment );
ce.addField( field );
}
return fieldName;
}
/** Ensure the listenersList exists. Used for generating
* multicast event source support implemented by javax.swing.event.EventListenerList.
* Searches the source for suitable field. If the field does not exists
* creates new one.
* @param ce Class to operate on.
* @param type Type of the Event Listener.
* @throws SourceException If the modification of the source is impossible.
* @return Name of found or newly created field.
*/
static String eventListenerListField( ClassElement ce, Type type ) throws SourceException {
String fieldName = null;
Identifier fieldTypeId = Identifier.create( "javax.swing.event.EventListenerList" ); // NOI18N
FieldElement[] fields = ce.getFields();
for( int i = 0; i < fields.length; i++ ) { // Try to find suitable field
if ( fields[i].getType().isClass() &&
fields[i].getType().getClassName().compareTo( fieldTypeId, false ) ) {
fieldName = fields[i].getName().getName();
break;
}
}
if ( fieldName == null ) { // Field not found we create new
fieldName = "listenerList"; // NOI18N
FieldElement field = new FieldElement();
field.setName( Identifier.create( fieldName ) );
field.setType( Type.createClass( fieldTypeId ) );
field.setModifiers( Modifier.PRIVATE );
field.setInitValue( " null" ); // NOI18N
String comment = MessageFormat.format( bundle.getString( "COMMENT_EventListenerList" ),
new Object[] { type.getClassName().getName() } );
field.getJavaDoc().setRawText( comment );
ce.addField( field );
}
return fieldName;
}
/** Ensure that listener field for unicast exists. Used for generating
* unicast event source support.
* Searches the source for suitable field. If the field does not exists
* creates new one.
* @param ce Class to operate on.
* @param type Type of the Event Listener.
* @throws SourceException If the modification of the source is impossible.
*/
static void unicastListenerField( ClassElement ce, Type type ) throws SourceException {
String fieldName = null;
String fieldNameToFind = Introspector.decapitalize( type.getClassName().getName() );
if ( fieldNameToFind.equals( type.getClassName().getName() ) ) {
fieldNameToFind = new String( "listener" + fieldNameToFind ); // NOI18N
}
FieldElement[] fields = ce.getFields();
for( int i = 0; i < fields.length; i++ ) { // Try to find suitable field
if ( fields[i].getType().isClass() &&
fields[i].getType().getClassName().compareTo( type.getClassName(), false ) &&
fields[i].getName().getName().equals( fieldNameToFind ) ) {
fieldName = fields[i].getName().getName();
break;
}
}
if ( fieldName == null ) { // Field not found we create new
fieldName = fieldNameToFind;
FieldElement field = new FieldElement();
field.setName( Identifier.create( fieldName ) );
field.setType( type );
field.setModifiers( Modifier.PRIVATE | Modifier.TRANSIENT );
field.setInitValue( " null" ); // NOI18N
String comment = MessageFormat.format( bundle.getString( "COMMENT_UnicastEventListener" ),
new Object[] { type.getClassName().getName() } );
field.getJavaDoc().setRawText( comment );
ce.addField( field );
}
}
static String mcAddBody( Type type, int implementation, String listenerList ) {
String fieldName = Introspector.decapitalize( type.getClassName().getName() ) + "List"; // NOI18N
StringBuffer body = new StringBuffer( 50 );
if ( listenerList == null )
listenerList = "listenerList"; // NOI18N
body.append( "\n"); // NOI18N
if ( implementation == 1 ) {
body.append( TAB + "if (" ).append( fieldName ).append( " == null ) {\n" ); // NOI18N
body.append( TABx2 ).append( fieldName ).append( " = new java.util.ArrayList ();\n" ); // NOI18N
body.append( TAB ).append( "}\n" ); // NOI18N
body.append( TAB + fieldName ).append( ".add (listener);\n" ); // NOI18N
}
else if ( implementation == 2 ) {
body.append( TAB + "if (" ).append( listenerList ).append( " == null ) {\n" ); // NOI18N
body.append( TABx2 ).append( listenerList ).append( " = new javax.swing.event.EventListenerList();\n" ); // NOI18N
body.append( TAB ).append( "}\n" ); // NOI18N
body.append( TAB + listenerList ).append( ".add (" ); // NOI18N
body.append( type.toString()).append( ".class, listener);\n" ); // NOI18N
}
return body.toString();
}
static String mcRemoveBody( Type type, int implementation, String listenerList ) {
String fieldName = Introspector.decapitalize( type.getClassName().getName() ) + "List"; // NOI18N
if ( listenerList == null )
listenerList = "listenerList"; // NOI18N
StringBuffer body = new StringBuffer( 50 );
body.append( "\n"); // NOI18N
if ( implementation == 1 ) {
body.append( TAB + "if (" ).append( fieldName ).append( " != null ) {\n" ); // NOI18N
body.append( TABx2 + fieldName ).append( ".remove (listener);\n" ); // NOI18N
body.append( TAB ).append( "}\n" ); // NOI18N
}
else if ( implementation == 2 ) {
body.append( TAB + listenerList ).append( ".remove (" ); // NOI18N
body.append( type.toString()).append( ".class, listener);\n" ); // NOI18N
}
return body.toString();
}
static String ucAddBody( Type type, int implementation ) {
String fieldName = Introspector.decapitalize( type.getClassName().getName() );
if ( fieldName.equals( type.getClassName().getName() ) ) {
fieldName = new String( "listener" + fieldName ); // NOI18N
}
StringBuffer body = new StringBuffer( 50 );
body.append( "\n"); // NOI18N
if ( implementation == 1 ) {
body.append( TAB + "if (").append( fieldName ).append( " != null) {\n" ); // NOI18N
body.append( TABx2 + "throw new java.util.TooManyListenersException ();\n" ); // NOI18N
body.append( TAB + "}\n" ); // NOI18N
body.append( TAB + fieldName ).append( " = listener;\n" ); // NOI18N
}
return body.toString();
}
static String ucRemoveBody( Type type, int implementation ) {
String fieldName = Introspector.decapitalize( type.getClassName().getName() );
if ( fieldName.equals( type.getClassName().getName() ) ) {
fieldName = new String( "listener" + fieldName ); // NOI18N
}
StringBuffer body = new StringBuffer( 50 );
body.append( "\n"); // NOI18N
if ( implementation == 1 ) {
body.append( TAB + fieldName ).append( " = null;\n" ); // NOI18N
}
return body.toString();
}
static void fireMethod( ClassElement classElement, Type type,
MethodElement method, int implementation,
String listenerList,
boolean passEvent )
throws SourceException {
if ( listenerList == null )
listenerList = "listenerList"; // NOI18N
Identifier methodId = Identifier.create(
"fire" + // NOI18N
Pattern.capitalizeFirstLetter( type.getClassName().getName() ) +
Pattern.capitalizeFirstLetter( method.getName().getName() ) );
MethodElement newMethod = null;
Type eventType = null;
MethodParameter params[] = method.getParameters();
if ( params.length > 0 )
eventType = params[0].getType();
else
eventType = Type.createClass( Identifier.create( "java.util.EventObject" ) ); // NOI18N
ClassElement eventClass = ClassElement.forName( eventType.toString() );
//addMethod = classElement.getMethod( addMethodId, new Type[] { listenerType } );
//if ( addMethod == null ) {
newMethod = new MethodElement();
newMethod.setName( methodId );
newMethod.setReturn( Type.VOID );
newMethod.setModifiers( Modifier.PRIVATE );
MethodParameter[] newMethodParams = generateFireParameters( eventType, eventClass, passEvent );
newMethod.setParameters( newMethodParams );
StringBuffer body = new StringBuffer( 80 );
body.append( "\n" ); // NOI18N
if ( implementation == 1 ) {
String fieldName = Introspector.decapitalize( type.getClassName().getName() ) + "List"; // NOI18N
body.append( TAB + "java.util.ArrayList list;\n" ); // NOI18N
if ( usesConstructorParameters( eventClass, passEvent ) ) {
body.append( TAB + eventType.toString() ).append( " e = new "); // NOI18N
body.append( eventType.toString() ).append( " (" ); // NOI18N
body.append( fireParameterstoString( newMethodParams ) );
body.append(");\n"); // NOI18N
}
body.append( TAB + "synchronized (this) {\n" + TABx2 + "list = (java.util.ArrayList)" ); // NOI18N
body.append( fieldName ).append( ".clone ();\n" + TAB +"}\n" ); // NOI18N
body.append( TAB + "for (int i = 0; i < list.size (); i++) {\n" ); // NOI18N
body.append( TABx2 + "((" ).append( type.toString() ); // NOI18N
body.append( ")list.get (i)).").append( method.getName() ); // NOI18N
body.append(" ("); // NOI18N
if ( usesConstructorParameters( eventClass, passEvent ) ) {
body.append( "e" ); // NOI18N
}
else {
body.append( fireParameterstoString( newMethodParams ) ); // the event parameter
}
body.append( ");\n" + TAB + "}\n" ); // NOI18N
}
else if ( implementation == 2 ) {
String fooEvent = "theEvent"; // NOI18N
if ( usesConstructorParameters( eventClass, passEvent ) ) {
body.append( TAB + eventType.toString() ).append( " e = null;\n "); // NOI18N
}
body.append( TAB + "Object[] listeners = ").append(listenerList).append(".getListenerList ();\n" ); // NOI18N
body.append( TAB + "for (int i = listeners.length-2; i>=0; i-=2) {\n"); // NOI18N
body.append( TABx2 + "if (listeners[i]==" ).append( type.toString()).append( ".class) {\n" ); // NOI18N
if ( usesConstructorParameters( eventClass, passEvent ) ) {
body.append( TABx3 + "if (e == null)\n" ); // NOI18N
body.append( TABx2 + TABx2 + "e = new ").append( eventType.toString() ).append( " (" ); // NOI18N
body.append( fireParameterstoString( newMethodParams ) );
body.append( ");\n" ); // NOI18N
}
body.append( TABx3 + "((").append(type.toString()).append(")listeners[i+1]).").append(method.getName()); // NOI18N
body.append(" ("); // NOI18N
if ( usesConstructorParameters( eventClass, passEvent ) ) {
body.append( "e" ); // the created event // NOI18N
}
else {
body.append( fireParameterstoString( newMethodParams ) ); // the event parameter
}
body.append( ");\n" + TABx2 + "}\n" + TAB + "}\n"); // NOI18N
}
newMethod.setBody( body.toString() );
StringBuffer comment = new StringBuffer ( bundle.getString( "COMMENT_FireMethodMC" ) );
if ( !usesConstructorParameters( eventClass, passEvent ) ) {
comment.append( "\n@param e The event to be fired\n" ); // NOI18N
}
else {
comment.append( fireParametersComment( newMethodParams, eventType.getClassName().getName() ) );
}
newMethod.getJavaDoc().setRawText( comment.toString() );
classElement.addMethod( newMethod );
//}
}
static void unicastFireMethod( ClassElement classElement, Type type,
MethodElement method, int implementation,
boolean passEvent )
throws SourceException {
Identifier methodId = Identifier.create(
"fire" + // NOI18N
Pattern.capitalizeFirstLetter( type.getClassName().getName() ) +
Pattern.capitalizeFirstLetter( method.getName().getName() ) );
MethodElement newMethod = null;
Type eventType = null;
MethodParameter params[] = method.getParameters();
if ( params.length > 0 )
eventType = params[0].getType();
else
eventType = Type.createClass( Identifier.create( "java.util.EventObject" ) ); // NOI18N
ClassElement eventClass = ClassElement.forName( eventType.toString() );
//addMethod = classElement.getMethod( addMethodId, new Type[] { listenerType } );
//if ( addMethod == null ) {
newMethod = new MethodElement();
newMethod.setName( methodId );
newMethod.setReturn( Type.VOID );
newMethod.setModifiers( Modifier.PRIVATE );
MethodParameter[] newMethodParams = generateFireParameters( eventType, eventClass, passEvent );
newMethod.setParameters( newMethodParams );
StringBuffer body = new StringBuffer( 80 );
body.append( "\n" ); // NOI18N
if ( implementation == 1 ) {
String fieldName = Introspector.decapitalize( type.getClassName().getName() );
if ( fieldName.equals( type.getClassName().getName() ) ) {
fieldName = new String( "listener" + fieldName ); // NOI18N
}
if ( usesConstructorParameters( eventClass, passEvent ) ) {
body.append( TAB + eventType.toString() ).append( " e = new "); // NOI18N
body.append( eventType.toString() ).append( " (" ); // NOI18N
body.append( fireParameterstoString( newMethodParams ) );
body.append(");\n"); // NOI18N
}
body.append( TAB + fieldName ).append( "." ).append( method.getName() ); // NOI18N
body.append(" ("); // NOI18N
if ( usesConstructorParameters( eventClass, passEvent ) ) {
body.append( "e" ); // NOI18N
}
else {
body.append( fireParameterstoString( newMethodParams ) ); // the event parameter
}
body.append( ");\n" ); // NOI18N
}
newMethod.setBody( body.toString() );
StringBuffer comment = new StringBuffer ( bundle.getString( "COMMENT_FireMethodUC" ) );
if ( !usesConstructorParameters( eventClass, passEvent ) ) {
comment.append( "\n@param e The event to be fired\n" ); // NOI18N
}
else {
comment.append( fireParametersComment( newMethodParams, eventType.getClassName().getName() ) ); // the event parameter
}
newMethod.getJavaDoc().setRawText( comment.toString() );
classElement.addMethod( newMethod );
//}
}
static boolean usesConstructorParameters( ClassElement eventClass, boolean passEvent ) {
if ( passEvent || eventClass == null || eventClass.getConstructors().length > 1 )
return false;
else
return true;
}
static MethodParameter[] generateFireParameters( Type eventType, ClassElement eventClass, boolean passEvent ) {
if ( !usesConstructorParameters( eventClass, passEvent ) ) {
return new MethodParameter[]
{ new MethodParameter( "event", eventType, false ) }; // NOI18N
}
else {
ConstructorElement constructor = eventClass.getConstructors()[0];
MethodParameter[] params = constructor.getParameters();
MethodParameter[] result = new MethodParameter[ params.length ];
for ( int i = 0; i < params.length; i++ ) {
result[i] = new MethodParameter( "param" + (i + 1), params[i].getType(), false ); // NOI18N
}
return result;
}
}
static String fireParameterstoString( MethodParameter[] params ) {
StringBuffer buffer = new StringBuffer( 60 );
for( int i = 0; i < params.length; i++ ) {
buffer.append( params[i].getName() );
if ( i < params.length -1 )
buffer.append( ", " ); // NOI18N
}
return buffer.toString();
}
static String fireParametersComment( MethodParameter[] params, String evntType ) {
StringBuffer buffer = new StringBuffer( 60 );
for( int i = 0; i < params.length; i++ ) {
buffer.append( "\n@param ").append( params[i].getName() ); // NOI18N
buffer.append( " Parameter #" ).append( i + 1 ).append( " of the <CODE>" ); // NOI18N
buffer.append( evntType ).append( "<CODE> constructor." ); // NOI18N
}
buffer.append( "\n" ); // NOI18N
return buffer.toString();
}
// UTILITY METHODS ----------------------------------------------------------
/** For primitive {@link org.openide.src.Type type} finds class for wrapping it into object.
* E.g. <CODE>Type.BOOLEAN -> Boolean</CODE>
* @param type Primitive type.
* @return Class which wraps the primitive type.
*/
private static String getWrapperClassName(Type type) {
if ( type.isClass() )
return type.getClassName().getName();
else if ( type == Type.BOOLEAN )
return "Boolean"; // NOI18N
else if ( type == Type.BYTE )
return "Byte"; // NOI18N
else if ( type == Type.DOUBLE )
return "Double"; // NOI18N
else if ( type == Type.FLOAT )
return "Float"; // NOI18N
else if ( type == Type.CHAR )
return "Character"; // NOI18N
else if ( type == Type.INT )
return "Integer"; // NOI18N
else if ( type == Type.LONG )
return "Long"; // NOI18N
else if ( type == Type.SHORT )
return "Short"; // NOI18N
else
return "Object"; // NOI18N
}
}
/*
* Log
* 10 Gandalf 1.9 1/17/00 Petr Hrebejk Indexed property setter
* body fix mk2
* 9 Gandalf 1.8 1/15/00 Petr Hrebejk BugFix 5386, 5385, 5393
* and new WeakListener implementation
* 8 Gandalf 1.7 1/13/00 Petr Hrebejk i18n mk3
* 7 Gandalf 1.6 1/12/00 Petr Hrebejk i18n
* 6 Gandalf 1.5 11/10/99 Petr Hrebejk Generation of new
* EventListenerList added to MultiCast event sources
* 5 Gandalf 1.4 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 4 Gandalf 1.3 10/6/99 Petr Hrebejk Formating fix
* 3 Gandalf 1.2 9/13/99 Petr Hrebejk Creating multiple
* Properties/EventSet with the same name vorbiden. Forms made i18n
* 2 Gandalf 1.1 7/26/99 Petr Hrebejk BeanInfo fix & Code
* generation fix
* 1 Gandalf 1.0 6/28/99 Petr Hrebejk
* $
java.awt.event.WindowListener */